package pl.ptemich.eav.engine.physics.impl;

import org.newdawn.slick.SlickException;

import pl.ptemich.eav.engine.Point;
import pl.ptemich.eav.engine.physics.DynamicObject;
import pl.ptemich.eav.engine.physics.DynamicParameters;
import pl.ptemich.eav.engine.physics.ShapeParameters;
import pl.ptemich.eav.engine.physics.Updatable;

public class DynamicObjectImpl extends StaticObjectImpl implements DynamicObject, Updatable {

  private DynamicParameters dynamicParams;
  
  private float xSpeed;
  
  private float ySpeed;
  
  private boolean moves = false;
  
  private boolean jumps = false;
  
  private boolean falls = true;
  
  private float currentJumpHeight;
  
  private float targetJumpHeight;
  
  public DynamicObjectImpl(Point worldPosition, float marginX, float marginY, ShapeParameters shapeParematers, DynamicParameters dynamicParams)  throws SlickException {
    super(worldPosition, marginX, marginY, shapeParematers);
    this.dynamicParams = dynamicParams;
  }
  
  @Override
  public void update(int delta) {
    if (moves) {
      moveHorizontaly(xSpeed * delta);
      setHorizontLimits(getMarginX(), Float.MAX_VALUE);      
    }
    
    if (jumps || falls) {
      float yPlacement = ySpeed * delta;
      moveVerticaly(yPlacement); 
      currentJumpHeight += yPlacement;
      if (targetJumpHeight < currentJumpHeight) {
        falls = true;
        jumps = false;
        ySpeed = dynamicParams.getFallingSpeed();
      }
    }
    setVerticalLimits(getMarginX(), Float.MAX_VALUE); 
  }  
  
  @Override
  public void triggerJump(float jumpHeight) {
    if (!jumps && !falls) {
      currentJumpHeight = 0;
      targetJumpHeight = jumpHeight;
      ySpeed = dynamicParams.getJumpSpeed(); 
      jumps = true;
    }    
  }

  
  @Override
  public void setHorizontalSpeed(float speed) {
    xSpeed = speed;
    if (speed != 0) {
      moves = true;
    }
  }
  
  public DynamicParameters getDynamicParams() {
    return dynamicParams;
  }

  private void moveHorizontaly(float movement) {
    getWorldPosition().setPosX(getWorldPosition().getPosX() + movement);
  }

  private void moveVerticaly(float movement) {
    getWorldPosition().setPosY(getWorldPosition().getPosY() + movement);
  }  
  
  private void setHorizontLimits(float minPosition, float maxPosition) {
    if (getWorldPosition().getPosX() < minPosition) {
      getWorldPosition().setPosX(minPosition);
    }

    if (getWorldPosition().getPosX() > maxPosition) {
      getWorldPosition().setPosX(maxPosition);
    }
  }

  private void setVerticalLimits(float minPosition, float maxPosition) {
    if (getWorldPosition().getPosY() < minPosition) {
      getWorldPosition().setPosY(minPosition);
      falls = false;   
    }

    if (getWorldPosition().getPosY() > maxPosition) {
      getWorldPosition().setPosY(maxPosition);
    }
  }   
  
}
